﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RadowCore.Models
{
    /// <summary>
    /// The policy, which consists of a list of rules.
    /// </summary>
    class Policy
    {
        private string m_name;
        /// <summary>
        /// the policy name
        /// </summary>
        public string Name
        {
            get { return m_name; }
            set { m_name = value; }
        }

        private List<Rule> m_ruleHashTable;
        /// <summary>
        /// a hash table contains all the policy rules as entries
        /// </summary>
        public List<Rule> RuleList
        {
            get { return m_ruleHashTable; }
            set { m_ruleHashTable = value; }
        }
        /// <summary>
        /// Default constructur, returns a new Policy object.
        /// </summary>
        public Policy()
        {
            this.RuleList = new List<Rule>();
        }
        /// <summary>
        /// Policy constructor, returns a new Policy object.
        /// </summary>
        /// <param name="policyName">The name of the policy</param>
        public Policy(string policyName)
        {
            this.Name = policyName;
            this.RuleList = new List<Rule>();
        }
        /// <summary>
        ///  Policy constructor, returns a new Policy object.
        /// </summary>
        /// <param name="policyName">The name of the policy</param>
        /// <param name="ruleSet">The rules's set of the policy</param>
        public Policy(string policyName,   List<Rule> ruleSet)
        {
            this.Name = policyName;
            this.RuleList = ruleSet;
        }
        
        public void LoadFromDB()
        {
            RadowDataClassesDataContext _db = new RadowDataClassesDataContext();
            Policy_DB policy = _db.Policy_DBs.Where(p => p.PolicyName == this.Name).FirstOrDefault();
            foreach (Rule_DB rule in policy.Rule_DBs)
            {
                Rule r = new Rule();
                r.Source = rule.RuleSource;
                r.Destination = rule.RuleDestination;                
                foreach(Disjunct_DB disjunct in rule.Disjunct_DBs)
                {
                    DisjunctNode d = new DisjunctNode();
                    foreach (Conjuct_DB conjunct in disjunct.Conjuct_DBs)
                    {
                        ConjunctNode c = new ConjunctNode();
                        foreach (Flow_DB flow in conjunct.Flow_DBs)
                        {
                            FlowNode f = new FlowNode(flow.FlowSource,flow.FlowDestination);
                            c.Flows.Add(f);
                        }
                        d.Conjuncts.Add(c);
                    }
                    r.Exception = d;
                }
                this.RuleList.Add( r);
            }
        }
        public void StoreInDB()
        {
            RadowDataClassesDataContext _db = new RadowDataClassesDataContext();            
            Policy_DB policy = new Policy_DB();
            policy.PolicyName = this.Name;
            foreach (Rule rule in this.RuleList)
            {
                Rule_DB r = new Rule_DB();
                r.RuleSource = rule.Source;
                r.RuleDestination = rule.Destination;
                DisjunctNode disjunct = (DisjunctNode)rule.Exception;
                //foreach (DisjunctNode disjunct in rule.Exception)
                //{
                    Disjunct_DB d = new Disjunct_DB();
                    foreach (ConjunctNode conjunct in disjunct.Conjuncts)
                    {
                        Conjuct_DB c = new Conjuct_DB();
                        foreach (FlowNode flow in conjunct.Flows)
                        {
                            Flow_DB f = new Flow_DB();
                            f.FlowSource = flow.Source;
                            f.FlowDestination = flow.Destination;
                            _db.Flow_DBs.InsertOnSubmit(f);
                            c.Flow_DBs.Add(f);                            
                        }
                        _db.Conjuct_DBs.InsertOnSubmit(c);
                        d.Conjuct_DBs.Add(c);
                    }
                    _db.Disjunct_DBs.InsertOnSubmit(d);
                    r.Disjunct_DBs.Add(d);
                //}
                _db.Rule_DBs.InsertOnSubmit(r);
                policy.Rule_DBs.Add(r);
            }
            _db.Policy_DBs.InsertOnSubmit(policy);
            _db.SubmitChanges();
        }
    }
}
